package org.dromara.web.controller.app;


import cn.dev33.satoken.annotation.SaIgnore;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.IpUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.web.controller.app.req.ChatBody;
import org.dromara.web.controller.app.req.TextToImageBody;
import org.dromara.web.plugins.aliasr.AliAsrService;
import org.dromara.web.plugins.provider.SsEmitterResponseBody;
import org.dromara.web.service.business.ChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;


/**
 * 聊天相关
 */
@Slf4j
@Controller
@RequestMapping("/app/chat")
public class AppChatSSEController extends BaseController {

    @Autowired
    ChatService chatService;
    @Autowired
    ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    AliAsrService aliAsrService;

    /**
     * 发送聊天内容
     *
     * @param body
     * @return
     */
    @Operation(
        requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
            content = @Content(
                schema = @Schema(implementation = ChatBody.class)
            )
        )
    )
    @PostMapping("/completion")
    public SseEmitter sseStreamChat(@Validated @RequestBody ChatBody body, @RequestHeader("Content-Language") String lang, HttpServletRequest request) {
        String ip = IpUtils.getIpAddr(request);
        SseEmitter emitter = new SseEmitter();
        if (StringUtils.isEmpty(lang)) {
            lang = "en_US";
        }
        final String language = lang;
        LoginUser user = LoginHelper.getAppLoginUser();
        threadPoolTaskExecutor.execute(() -> {
            // 异步任务需要设置默认多语言
            Locale locale;
            if (language.contains("_")) {
                String[] split = language.split("_");
                locale = new Locale(split[0], split[1]);
            } else {
                locale = new Locale(language);
            }
            Locale.setDefault(locale);
            body.setAppLocale(language);
            chatService.chatMessage(body, emitter, user, language, ip);
        });
        return emitter;
    }


    /**
     * 不需要登录调用大模型
     *
     * @param body
     * @return
     */
    @Operation
    @SaIgnore
    @PostMapping("/completion_single")
    public SseEmitter sseStreamChatTest(@Validated @RequestBody ChatBody body) {
        SseEmitter emitter = new SseEmitter();
        threadPoolTaskExecutor.execute(() -> {
            chatService.chatMessage(body, emitter);
        });


        return emitter;
    }


    /**
     * @param body
     * @return
     */
    @Operation(
        requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
            content = @Content(
                schema = @Schema(implementation = TextToImageBody.class)
            )
        )
    )
    @ResponseBody
    @PostMapping("/image")
    public R<SsEmitterResponseBody> imageGenerate(@RequestBody TextToImageBody body) {

        SsEmitterResponseBody image = chatService.ImageChatMessage(body, LoginHelper.getAppLoginUser());

//        SsEmitterResponseBody image = SsEmitterResponseBody.builder()
////                .image(image)
//                .image("http://47.97.254.154:9000/ruoyi/2025/01/17/2ed903a66f4c4d6599402dccfc0959b9.png")
//                .sessionId(body.getSessionId())
//                .status(SsEmitterResponseBody.STATUS_OK)
//                .build();

        return R.ok("", image);
    }


    @SaIgnore
    @ResponseBody
    @PostMapping("/imageTest")
    public R<String> imageTest(@RequestBody TextToImageBody body) {

        String image = chatService.ImageChatMessage(body);
        return R.ok("", image);
    }


    @SaIgnore
    @ResponseBody
    @PostMapping(value = "/voice_to_text", consumes = "application/octet-stream")
    public R<String> voiceToText(@RequestBody byte[] bytes) {

        return R.ok("", aliAsrService.voiceToText(bytes));
    }


    @SaIgnore
    @ResponseBody
    @PostMapping(value = "/voice_to_text_file")
    public R<String> voiceToText(MultipartFile file) {
        try {
            String resp = aliAsrService.voiceToText(file.getBytes());
            return R.ok("", resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.ok("", null);
    }


    @SaIgnore
    @ResponseBody
    @GetMapping(value = "/text_to_voice")
    public void voiceToText(String text, HttpServletResponse response) throws IOException {
        byte[] bytes = aliAsrService.textToVoice(text);
        response.setContentType("audio/mpeg");
        response.setContentLength(bytes.length);
        response.getOutputStream().write(bytes);
        response.getOutputStream().flush();
    }


    @SaIgnore
    @GetMapping("/stream")
    public SseEmitter handleSse() {
        SseEmitter emitter = new SseEmitter();

        // 在新线程中发送事件以避免阻塞主线程
        new Thread(() -> {
            try {
                for (int i = 0; i < 5; i++) {
                    Map<String, Object> event = new HashMap<>();
                    event.put("id", i);
                    event.put("data", "message " + i);
                    emitter.send(event);
                    Thread.sleep(1000); // 每秒发送一次事件
                }
                emitter.complete(); // 完成事件流发送
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e); // 发送错误
            }
        }).start();

        return emitter;
    }


}
